<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>合成事件原理</title>
    <style>
        .center {
            position: absolute;
            top:0;
            right:0;
            bottom:0;
            left:0;
            margin:auto;
        }
        #root {
            width: 300px;
            height: 300px;
            background-color: gold;
            position: absolute;
            top:0;
            right:0;
            bottom:0;
            left:0;
            margin:auto;
        }
        #outer {
            width: 200px;
            height: 200px;
            background-color: blue;
        }
        #inner {
            width: 100px;
            height: 100px;
            background-color: green;
        }
    </style>
</head>
<body>
    <div id="root" class='center'>
        <div id="outer" class='center'>
            <div id="inner" class='center'></div>
        </div>
    </div>
</body>
<script>
    const root = document.querySelector('#root');
    const outer = document.querySelector('#outer');
    const inner = document.querySelector('#inner');
    
    // 第一步：经过视图渲染解析,outer/inner上都有onXxx/onXxxCapture这样的属性,自定义属性 【遇到合成事件绑定属性，并没有给这个元素做事件绑定，而是给这个元素设置的对应属性：合成事件属性】
    // <div id="outer" className='center'  onClick={() =>{console.log('outer 冒泡 [合成]'); }}onClickCapture={() =>{console.log('outer 捕获 [合成]');}}>
    //     <div id="inner" className='center'  onClick={() =>{console.log('inner 冒泡 [合成]');}} onClickCapture={() =>{console.log('inner 捕获 [合成]');}}></div>
    // </div>
    outer.onClick = () => {console.log('outer 冒泡 [合成]'); }
    outer.onClickCapture = (ev) => {console.log('outer 捕获 [合成]', 'ev ...',ev); }

    inner.onClick = () => {console.log('inner 冒泡 [合成]'); }
    inner.onClickCapture = () => {console.log('inner 捕获 [合成]'); }


    // 第二步：给#root这个容器做事件绑定，捕获+冒泡都做了，root上帮定的方法执行，把所有规划的路径中，有合成事件属性的都执行即可！
    //给root容器做捕获 -> true
    root.addEventListener('click', (ev) => {
        const path = event.path || ev.composedPath(); // 兼容处理   // 所有祖先元素-> [事件源 -> ... -> window]  [div#inner.center, div#outer.center, div#root.center, body, html, document, Window]
        //console.log(path);
        [...path].reverse().forEach(ele => {
            const handle = ele.onClickCapture;
            if(handle) {
                handle(syntheticEvent(ev));
            }
        }); 
         
    },true);

    //给root容器做冒泡 -> true
     root.addEventListener('click', (ev) => {
        const path = event.path || ev.composedPath();
        
        path.forEach(ele => {
             const handle = ele.onClick;
            if(handle) {
                handle(syntheticEvent(ev));
            }
        })
    },false);

    /* 处理合成事件对象 */
    const syntheticEvent = (ev) => {
        return {
            stopProgation:() =>{},
            preventDefault:() => {},
            nativeEvent: ev,
        }
    }
</script>
</html>